/**
 * 
 */
package ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.elementstemplate;

import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.EList;
import org.pnml.tools.epnk.pnmlcoremodel.AnnotationGraphics;
import org.pnml.tools.epnk.pnmlcoremodel.Coordinate;
import org.pnml.tools.epnk.pnmlcoremodel.Name;
import org.pnml.tools.epnk.pnmlcoremodel.PlaceNode;
import org.pnml.tools.epnk.pnmlcoremodel.PnmlcoremodelFactory;
import org.pnml.tools.epnk.pntypes.hlpng.pntd.hlpngdefinition.Declaration;

import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Arc;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Page;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Place;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.RefPlace;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Transition;
import ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.NodeStructure;
import ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.TreeInterface;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.InteractionPath;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.InteractionProtocolElement;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Loop;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.LoopType;

/**
 * @author Neri
 *
 */
public class LoopUpcolbpipStructure extends ChoreographyStructure {
	
	public LoopUpcolbpipStructure(Integer i){		
		super();		
		//Name		
		AnnotationGraphics graphicsName = PnmlcoremodelFactory.eINSTANCE
				.createAnnotationGraphics();
		
		Name nameLabel = PnmlcoremodelFactory.eINSTANCE.createName();
		
		Coordinate coordinate2 = PnmlcoremodelFactory.eINSTANCE.createCoordinate();
		
		coordinate2.setX(-9);
		coordinate2.setY( -39);
		
		graphicsName.setOffset(coordinate2);
		
		nameLabel.setText("LOOP" +i);
		nameLabel.setGraphics(graphicsName);
		
		this.abstractPage.setName(nameLabel);
	}
	
	@Override
	public void createPageStructure(NodeStructure node, TreeInterface tree, PlaceNode placeIn, PlaceNode placeOut, EList<Declaration> ginetDeclarations, Place termination){		
		this.tree = tree;
		
		this.fillVarDeclAndNameSort(ginetDeclarations);
		
		Map<InteractionPath, EList<InteractionProtocolElement>> childrenCount = node.getChildrens();
		
		boolean whitRefPlaces = placeIn != null && placeOut != null;
		
		if(((Loop)node.getNode()).getLoopType().equals(LoopType.WHILE)){
			RefPlace refPlaceIn = null; 
			Place placeLoopIn = null;
			if(whitRefPlaces){
				refPlaceIn = this.createRefPlace("InPlace",  3, 2, "InPlace", -4, -4, "1", placeIn);
			}else{
				placeLoopIn = createPlace("InPlace", 3, 2, "InPlace", -4, -4, this.getVarDec("gi"), 6, 21, true, "1");
			}
			
			Transition transition1 = this.createTransition("continue", 5, 1, "continue", -4, -9, "1", "1", null);

			Transition transition3 = this.createTransition("finalize_loop", 4, 3, "finalize_loop", -4, -9, "1", "1", null);
			
			Place place2 = createPlace("iterate", 5, 2, "iterate", -4, -4, this.getVarDec("gi"), 6, 21, true, "1");
			
			RefPlace refPlaceOut = null; 
			Place placeLoopOut = null;
			if(whitRefPlaces){
				refPlaceOut = this.createRefPlace("OutPlace", 5, 3, "OutPlace", -4, -4, "1", placeOut);
			}else{
				placeLoopOut = createPlace("OutPlace", 5, 3, "OutPlace", -4, -4, this.getVarDec("gi"), 6, 21, false, "1");
			}
			
			for(int i = 0; i<childrenCount.keySet().size(); i++){
				
				if(childrenCount.keySet().iterator().next().getElement().size() > 0){
											
					Page page = createPage("content", 4, 2, "content", -9, -39);
					
					if(whitRefPlaces){
						this.createInteractionProtocol(childrenCount.keySet().iterator().next().getElement(), 0, page, refPlaceIn, refPlaceOut, ginetDeclarations, termination);
					}else{
						this.createInteractionProtocol(childrenCount.keySet().iterator().next().getElement(), 0, page, placeLoopIn, placeLoopOut, ginetDeclarations, termination);
					}
				
					this.abstractPage.getObject().add(page);
					
				}else{
					Transition transition2 = this.createTransition("content", 4, 2, "content", -4, -9, "1", "1", null);
					
					Arc arc3;
					if(whitRefPlaces){
						arc3 = this.createArc("", this.getVarDec("gi"), -37, -3, refPlaceIn, transition2);
					}else{
						arc3 = this.createArc("", this.getVarDec("gi"), -37, -3, placeLoopIn, transition2);
					}
					Arc arc2 = this.createArc("", this.getVarDec("gi"), -9, -19, transition2, place2);
					
					this.abstractPage.getObject().add(arc3);
					this.abstractPage.getObject().add(arc2);
					this.abstractPage.getObject().add(transition2);			
				}
				
				i = childrenCount.keySet().size();
			}
			Arc arc2 = this.createArc("", this.getVarDec("gi"), -37, -3, place2, transition1);
			Arc arc3;
			if(whitRefPlaces){
				arc3 = this.createArc("", this.getVarDec("gi"), -37, -3, refPlaceIn, transition3);
			}else{
				arc3 = this.createArc("", this.getVarDec("gi"), -37, -3, placeLoopIn, transition3);
			}
			
			Arc arc4;
			if(whitRefPlaces){
				arc4 = this.createArc("", this.getVarDec("gi"), -37, -3, transition3, refPlaceOut);
			}else{
				arc4 = this.createArc("", this.getVarDec("gi"), -37, -3, transition3, placeLoopOut);
			}
			
			Arc arc5;
			if(whitRefPlaces){
				arc5 = this.createArc("", this.getVarDec("gi"), -37, -3, transition1, refPlaceIn);
			}else{
				arc5 = this.createArc("", this.getVarDec("gi"), -37, -3, transition1, placeLoopIn);
			}
			
			this.abstractPage.getObject().add(arc2);
			this.abstractPage.getObject().add(arc3);
			this.abstractPage.getObject().add(arc4);
			this.abstractPage.getObject().add(arc5);
			
			if(whitRefPlaces){
				this.abstractPage.getObject().add(refPlaceIn);
				this.abstractPage.getObject().add(refPlaceOut);
			}else{
				this.abstractPage.getObject().add(placeLoopIn);
				this.abstractPage.getObject().add(placeLoopOut);
			}
			this.abstractPage.getObject().add(place2);
			
			this.abstractPage.getObject().add(transition1);
			this.abstractPage.getObject().add(transition3);
		}else{
			
			RefPlace refPlaceIn = null; 
			Place placeLoopIn = null;
			if(whitRefPlaces){
				refPlaceIn = this.createRefPlace("InPlace",  3, 2, "InPlace", -4, -4, "1", placeIn);
			}else{
				placeLoopIn = createPlace("InPlace", 3, 2, "InPlace", -4, -4, this.getVarDec("gi"), 6, 21, true, "1");
			}
			
			Transition transition1 = this.createTransition("continue", 5, 1, "continue", -4, -9, "1", "1", null);

			Transition transition3 = this.createTransition("finalize_loop", 5, 3, "finalize_loop", -4, -9, "1", "1", null);
			
			Place place2 = createPlace("iterate", 5, 2, "iterate", -4, -4, this.getVarDec("gi"), 6, 21, true, "1");
			
			RefPlace refPlaceOut = null; 
			Place placeLoopOut = null;
			if(whitRefPlaces){
				refPlaceOut = this.createRefPlace("OutPlace", 5, 4, "OutPlace", -4, -4, "1", placeOut);
			}else{
				placeLoopOut = createPlace("OutPlace", 5, 4, "OutPlace", -4, -4, this.getVarDec("gi"), 6, 21, false, "1");
			}
			
			for(int i = 0; i<childrenCount.keySet().size(); i++){
				
				if(childrenCount.keySet().iterator().next().getElement().size() > 0){
											
					Page page = createPage("content", 4, 2, "content", -9, -39);
					
					if(whitRefPlaces){
						this.createInteractionProtocol(childrenCount.keySet().iterator().next().getElement(), 0, page, refPlaceIn, refPlaceOut, ginetDeclarations, termination);
					}else{
						this.createInteractionProtocol(childrenCount.keySet().iterator().next().getElement(), 0, page, placeLoopIn, placeLoopOut, ginetDeclarations, termination);
					}
				
					this.abstractPage.getObject().add(page);
					
				}else{
					Transition transition2 = this.createTransition("content", 4, 2, "content", -4, -9, "1", "1", null);
					
					Arc arc3;
					if(whitRefPlaces){
						arc3 = this.createArc("", this.getVarDec("gi"), -37, -3, refPlaceIn, transition2);
					}else{
						arc3 = this.createArc("", this.getVarDec("gi"), -37, -3, placeLoopIn, transition2);
					}
					Arc arc2 = this.createArc("", this.getVarDec("gi"), -9, -19, transition2, place2);
					
					this.abstractPage.getObject().add(arc3);
					this.abstractPage.getObject().add(arc2);
					this.abstractPage.getObject().add(transition2);			
				}
				
				i = childrenCount.keySet().size();
			}
			Arc arc2 = this.createArc("", this.getVarDec("gi"), -37, -3, place2, transition1);
			Arc arc3 = this.createArc("", this.getVarDec("gi"), -37, -3, place2, transition3);
			
			Arc arc4;
			if(whitRefPlaces){
				arc4 = this.createArc("", this.getVarDec("gi"), -37, -3, transition3, refPlaceOut);
			}else{
				arc4 = this.createArc("", this.getVarDec("gi"), -37, -3, transition3, placeLoopOut);
			}
			
			Arc arc5;
			if(whitRefPlaces){
				arc5 = this.createArc("", this.getVarDec("gi"), -37, -3, transition1, refPlaceIn);
			}else{
				arc5 = this.createArc("", this.getVarDec("gi"), -37, -3, transition1, placeLoopIn);
			}
			
			this.abstractPage.getObject().add(arc2);
			this.abstractPage.getObject().add(arc3);
			this.abstractPage.getObject().add(arc4);
			this.abstractPage.getObject().add(arc5);
			
			if(whitRefPlaces){
				this.abstractPage.getObject().add(refPlaceIn);
				this.abstractPage.getObject().add(refPlaceOut);
			}else{
				this.abstractPage.getObject().add(placeLoopIn);
				this.abstractPage.getObject().add(placeLoopOut);
			}
			this.abstractPage.getObject().add(place2);
			
			this.abstractPage.getObject().add(transition1);
			this.abstractPage.getObject().add(transition3);
		}
	}
}